/*
 * Copyright 2018-10-14 21:39:18 The JA-SIG Collaborative. All rights reserved.
 * distributed with thi file and available online at
 */
package com.lap.scp.erp.ao.impl;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.lap.scd.commons.ao.AbstractAO;
import com.lap.scd.commons.constant.RespCode;
import com.lap.scd.commons.core.exception.ManagerException;
import com.lap.scd.commons.page.Page;
import com.lap.scd.commons.page.PageResult;
import com.lap.scd.commons.page.PageUtils;
import com.lap.scd.commons.result.Resp;
import com.lap.scp.erp.ao.MaterielDetailAO;
import com.lap.scp.erp.core.MaterielDetailManager;
import com.lap.scp.erp.core.MaterielManager;
import com.lap.scp.erp.domain.MaterielDO;
import com.lap.scp.erp.domain.MaterielDetailDO;
import com.lap.scp.erp.domain.PaymentDO;
import com.lap.scp.erp.domain.PurchaseOrdersDO;
import com.lap.scp.erp.domain.SellOrdersDO;
import com.lap.scp.erp.query.MaterielDetailQueryVO;

/**
 * <pre>
 *   默认 物料明细明细信息应用实现类，提供物料明细明细信息相关的流程应用操作、查询等。
 *
 * </pre>
 * 
 * @author 劳水生 Exp
 * @Date 2018-10-14 21:39:18
 * @since 2.0.0
 */
@Service("materielDetailAO")
public class DefaultMaterielDetailAO extends AbstractAO implements MaterielDetailAO {
	/**
	 * 物料明细明细信息业务操作对象
	 */
	@Resource
	private MaterielDetailManager materielDetailManager;

	@Resource
	private MaterielManager materielManager;

	@Override
	public Resp<MaterielDetailDO> insertMaterielDetail(MaterielDetailDO detailDO) {
		Resp<MaterielDetailDO> resp = new Resp<>();
		try {
			validateAdd(resp, detailDO);
			if (resp.isSuccess()) {
				PurchaseOrdersDO purchaseDO = this.initMaterielLog(detailDO);
				materielDetailManager.insertMaterielDetail(detailDO, purchaseDO);
				resp.setData(detailDO);
			}
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(detailDO, e);
		}
		return resp;
	}

	private void validateAdd(Resp<?> resp, MaterielDetailDO detailDO) throws ManagerException {
		List<MaterielDetailDO> query = materielDetailManager.queryByMaterielId(detailDO.getMaterielId());
		if (query != null) {
			for (MaterielDetailDO materielDetailDO : query) {
				if (detailDO.getUnitPrice().equals(materielDetailDO.getUnitPrice())) {
					resp.putMsg(getMsg("704"));
				}
			}
		}
	}

	/**
	 * <pre>
	 * 初始化采购单
	 * </pre>
	 * 
	 * @param detailDO
	 * @return
	 * @throws ManagerException
	 */
	private PurchaseOrdersDO initMaterielLog(MaterielDetailDO detailDO) throws ManagerException {
		PurchaseOrdersDO purchaseDO = new PurchaseOrdersDO();
		purchaseDO.setMaterielId(detailDO.getMaterielId());
		purchaseDO.setQuantity(detailDO.getQuantity());
		purchaseDO.setUnitPrice(detailDO.getUnitPrice());
		purchaseDO.setRemark(detailDO.getRemark());
		purchaseDO.setPurchaseDate(detailDO.getOperatDate());
		purchaseDO.setCreatedBy(detailDO.getCreatedBy());
		purchaseDO.setUpdatedBy(detailDO.getUpdatedBy());

		MaterielDO materielDO = materielManager.queryById(detailDO.getMaterielId());
		if (materielDO != null) {
			purchaseDO.setMaterielName(materielDO.getName());
			purchaseDO.setMaterielSpec(materielDO.getSpec());
			purchaseDO.setSuppilerId(materielDO.getSuppilerId());
		}
		return purchaseDO;
	}

	@Override
	public Resp<Integer> deleteById(Integer materielDetailId) {
		Resp<Integer> resp = new Resp<>();
		try {
			int flag = materielDetailManager.deleteById(materielDetailId);
			resp.setData(flag);
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(materielDetailId, e);
		}
		return resp;
	}

	@Override
	public Resp<MaterielDetailDO> queryForAdd(Integer materielId) {
		Resp<MaterielDetailDO> resp = new Resp<>();
		try {
			MaterielDetailDO materielDetailDO = new MaterielDetailDO();
			MaterielDO materielDO = materielManager.queryById(materielId);

			materielDetailDO.setMaterielDO(materielDO);
			resp.setData(materielDetailDO);
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(materielId, e);
		}
		return resp;
	}

	@Override
	public Resp<MaterielDetailDO> queryById(Integer materielDetailId) {
		Resp<MaterielDetailDO> resp = new Resp<>();
		try {
			MaterielDetailDO detailDO = materielDetailManager.queryById(materielDetailId);
			if (detailDO != null) {
				MaterielDO materielDO = materielManager.queryById(detailDO.getMaterielId());
				detailDO.setMaterielDO(materielDO);
			}
			resp.setData(detailDO);
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(materielDetailId, e);
		}
		return resp;
	}

	@Override
	public PageResult<MaterielDetailDO> queryPage(Page page, MaterielDetailQueryVO queryVO) {
		PageResult<MaterielDetailDO> pr = new PageResult<>();
		try {
			List<MaterielDetailDO> list = materielDetailManager.queryPage(page, queryVO);

			PageUtils.copyPage(pr, page);
			pr.setData(list);
		} catch (Exception e) {
			pr.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(new Object[] { page, queryVO }, e);
		}
		return pr;
	}

	@Override
	public Resp<Integer> updateIn(MaterielDetailDO detailDO) {
		Resp<Integer> resp = new Resp<>();
		try {
			validateIn(resp, detailDO);
			if (resp.isSuccess()) {
				PurchaseOrdersDO purchaseDO = this.initMaterielLog(detailDO);
				int flag = materielDetailManager.updateIn(detailDO, purchaseDO);
				if (flag > 0) {
					resp.setData(flag);
				} else {
					resp.putMsg(getMsg("701"));
				}
			}
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(detailDO, e);
		}
		return resp;
	}

	private void validateIn(Resp<?> resp, MaterielDetailDO detailDO) {
		if (detailDO == null) {
			resp.putMsg(getMsg("001"));
		} else {
			if (detailDO.getQuantity() <= 0) {
				resp.putMsg(getMsg("702"));
			}
		}
	}

	@Override
	public Resp<Integer> updateOut(MaterielDetailDO detailDO, Integer contractId) {
		Resp<Integer> resp = new Resp<>();
		try {
			validateOut(resp, detailDO, contractId);
			if (resp.isSuccess()) {
				PaymentDO payDO = this.initPayment(detailDO, contractId);

				detailDO.setQuantity(-detailDO.getQuantity());
				SellOrdersDO sellDO = this.initSell(detailDO, contractId);
				int flag = materielDetailManager.updateOut(detailDO, payDO, sellDO);
				if (flag > 0) {
					resp.setData(flag);
				} else {
					resp.putMsg(getMsg("701"));
				}
			}
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(detailDO, e);
		}
		return resp;
	}

	/**
	 * 校验出库信息
	 * 
	 * @param resp
	 * @param detailDO
	 * @param contractId
	 */
	private void validateOut(Resp<?> resp, MaterielDetailDO detailDO, Integer contractId) {
		if (detailDO == null) {
			resp.putMsg(getMsg("001"));
		} else {
			if (detailDO.getQuantity() <= 0) {
				resp.putMsg(getMsg("702"));
			}
			if (contractId == null) {
				resp.putMsg(getMsg("703"));
			}
		}
	}

	/**
	 * <pre>
	 * 初始化采购单
	 * </pre>
	 * 
	 * @param detailDO
	 * @return
	 * @throws ManagerException
	 */
	private SellOrdersDO initSell(MaterielDetailDO detailDO, Integer contractId) throws ManagerException {
		SellOrdersDO sellDO = new SellOrdersDO();
		sellDO.setContractId(contractId);
		sellDO.setMaterielId(detailDO.getMaterielId());
		sellDO.setQuantity(detailDO.getQuantity());
		sellDO.setUnitPrice(detailDO.getUnitPrice());
		sellDO.setRemark(detailDO.getRemark());
		sellDO.setSellDate(detailDO.getOperatDate());
		sellDO.setCreatedBy(detailDO.getCreatedBy());
		sellDO.setUpdatedBy(detailDO.getUpdatedBy());

		MaterielDO materielDO = materielManager.queryById(detailDO.getMaterielId());
		if (materielDO != null) {
			sellDO.setMaterielName(materielDO.getName());
			sellDO.setMaterielSpec(materielDO.getSpec());
			sellDO.setSuppilerId(materielDO.getSuppilerId());
		}
		return sellDO;
	}

	/**
	 * 初始化出库成本核算
	 * 
	 * @param detailDO
	 * @param contractId
	 * @return
	 * @throws ManagerException
	 */
	private PaymentDO initPayment(MaterielDetailDO detailDO, Integer contractId) throws ManagerException {
		PaymentDO pay = new PaymentDO();
		pay.setType(10);// TODO
		pay.setAmount((int) Math.rint(detailDO.getQuantity() * detailDO.getUnitPrice()));
		pay.setBuyDate(new Date());
		pay.setContractId(contractId);
		pay.setRemark(detailDO.getRemark());
		pay.setCreatedBy(detailDO.getCreatedBy());
		pay.setUpdatedBy(detailDO.getUpdatedBy());

		MaterielDO materielDO = materielManager.queryById(detailDO.getMaterielId());
		if (materielDO != null) {
			StringBuilder sb = new StringBuilder();
			sb.append(materielDO.getName());
			sb.append("[");
			sb.append(materielDO.getSpec());
			sb.append("]");
			pay.setName(sb.toString());
		}
		return pay;
	}

	@Override
	public Resp<Integer> updateQuantity(MaterielDetailDO materielDetailDO) {
		Resp<Integer> resp = new Resp<>();
		try {
			if (resp.isSuccess()) {
				int flag = materielDetailManager.updateQuantity(materielDetailDO);
				if (flag > 0) {
					resp.setData(flag);
				} else {
					resp.putMsg(getMsg("701"));
				}
			}
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(materielDetailDO, e);
		}
		return resp;
	}

}
